﻿using SD.Common;
using SD.Infrastructure.EntityBase;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SlamDunk.MES.Domain.Entities.StockContext
{
    /// <summary>
    /// 库存单据明细
    /// </summary>
    public class StockOrderDetail : PlainEntity, ISortable
    {
        #region # 构造器

        #region 00.无参构造器
        /// <summary>
        /// 无参构造器
        /// </summary>
        protected StockOrderDetail()
        {
            //初始化导航属性
            this.RelatedBarcodes = new HashSet<StockOrderBarcode>();

            //默认值
            this.HasGeneratedBarcodes = null;
            this.HasPrintedBarcodes = null;
        }
        #endregion

        #region 01.创建库存单据明细构造器
        /// <summary>
        /// 创建库存单据明细构造器
        /// </summary>
        /// <param name="materialId">物料定义Id</param>
        /// <param name="materialLotId">物料批次Id</param>
        /// <param name="quantity">数量</param>
        /// <param name="sort">排序</param>
        /// <param name="description">描述</param>
        /// <param name="relatedBarcodeNos">库存单据条码编号集</param>
        public StockOrderDetail(Guid materialId, Guid? materialLotId, decimal quantity, int sort, string description, IEnumerable<string> relatedBarcodeNos)
            : this()
        {
            this.MaterialId = materialId;
            this.MaterialLotId = materialLotId;
            this.Quantity = quantity;
            this.Sort = sort;
            this.Description = description;

            //关联条码
            relatedBarcodeNos = relatedBarcodeNos?.Distinct().ToArray() ?? new string[0];
            IEnumerable<StockOrderBarcode> stockOrderBarcodes =
                from relatedBarcodeNo in relatedBarcodeNos
                select new StockOrderBarcode(relatedBarcodeNo);
            this.RelateBarcodes(stockOrderBarcodes);
        }
        #endregion

        #endregion

        #region # 属性

        #region 物料定义Id —— Guid MaterialId
        /// <summary>
        /// 物料定义Id
        /// </summary>
        public Guid MaterialId { get; private set; }
        #endregion

        #region 物料批次Id —— Guid? MaterialLotId
        /// <summary>
        /// 物料批次Id
        /// </summary>
        public Guid? MaterialLotId { get; private set; }
        #endregion

        #region 数量 —— decimal Quantity
        /// <summary>
        /// 数量
        /// </summary>
        public decimal Quantity { get; private set; }
        #endregion

        #region 是否已生成条码 —— bool? HasGeneratedBarcodes
        /// <summary>
        /// 是否已生成条码
        /// </summary>
        public bool? HasGeneratedBarcodes { get; private set; }
        #endregion

        #region 是否已打印条码 —— bool? HasPrintedBarcodes
        /// <summary>
        /// 是否已打印条码
        /// </summary>
        public bool? HasPrintedBarcodes { get; private set; }
        #endregion

        #region 排序 —— int Sort
        /// <summary>
        /// 排序
        /// </summary>
        public int Sort { get; private set; }
        #endregion

        #region 描述 —— string Description
        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; private set; }
        #endregion

        #region 只读属性 - 库存单据条码编号集 —— IEnumerable<string> RelatedBarcodeNos
        /// <summary>
        /// 只读属性 - 库存单据条码编号集
        /// </summary>
        public IEnumerable<string> RelatedBarcodeNos
        {
            get => this.RelatedBarcodes.Select(x => x.MaterialBarcodeNo);
        }
        #endregion

        #region 导航属性 - 库存单据 —— StockOrder StockOrder
        /// <summary>
        /// 导航属性 - 库存单据
        /// </summary>
        public virtual StockOrder StockOrder { get; internal set; }
        #endregion

        #region 导航属性 - 库存单据条码集 —— virtual ICollection<StockOrderBarcode> RelatedBarcodes
        /// <summary>
        /// 导航属性 - 库存单据条码集
        /// </summary>
        public virtual ICollection<StockOrderBarcode> RelatedBarcodes { get; private set; }
        #endregion

        #endregion

        #region # 方法

        #region 生成条码 —— void GenerateBarcodes()
        /// <summary>
        /// 生成条码
        /// </summary>
        public void GenerateBarcodes()
        {
            #region # 验证

            if (this.HasGeneratedBarcodes == true)
            {
                throw new InvalidOperationException("条码已生成，不可重新生成！");
            }

            #endregion

            this.HasGeneratedBarcodes = true;
            this.HasPrintedBarcodes = false;
        }
        #endregion

        #region 打印条码 —— void PrintBarcodes()
        /// <summary>
        /// 打印条码
        /// </summary>
        public void PrintBarcodes()
        {
            this.HasPrintedBarcodes = true;
        }
        #endregion

        #region 关联库存单据条码 —— void RelateBarcodes(IEnumerable<StockOrderBarcode>...
        /// <summary>
        /// 关联库存单据条码
        /// </summary>
        /// <param name="stockOrderBarcodes">库存单据条码集</param>
        public void RelateBarcodes(IEnumerable<StockOrderBarcode> stockOrderBarcodes)
        {
            stockOrderBarcodes = stockOrderBarcodes?.ToArray() ?? new StockOrderBarcode[0];

            this.ClearRelatedBarcodes();
            if (stockOrderBarcodes.Any())
            {
                this.RelatedBarcodes.AddRange(stockOrderBarcodes);
                foreach (StockOrderBarcode stockOrderBarcode in stockOrderBarcodes)
                {
                    stockOrderBarcode.StockOrderDetail = this;
                }
            }
        }
        #endregion

        #region 清空库存单据条码 —— void ClearRelatedBarcodes()
        /// <summary>
        /// 清空库存单据条码
        /// </summary>
        private void ClearRelatedBarcodes()
        {
            foreach (StockOrderBarcode relatedBarcode in this.RelatedBarcodes.ToArray())
            {
                this.RelatedBarcodes.Remove(relatedBarcode);
            }
        }
        #endregion

        #endregion
    }
}
